home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlb20 / lib / _addsubs.cpp < prev    next >
Text File  |  1992-03-30  |  5KB  |  190 lines

  1. #ifndef    __M68881__
  2. # ifndef sfp004
  3.  
  4. | single floating point add/subtract routine
  5. |
  6. | written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
  7. | Based on a 80x86 floating point packet from comp.os.minix, written by P.Housel
  8. |
  9. |
  10. | Revision 1.3, kub 01-90 :
  11. | added support for denormalized numbers
  12. |
  13. | Revision 1.2, kub 01-90 :
  14. | replace far shifts by swaps to gain speed (more optimization is of course
  15. | possible by doing shifts all in one intruction, but what about the rounding
  16. | bits)
  17. |
  18. | Revision 1.1, kub 12-89 :
  19. | Created single float version for 68000
  20. |
  21. | Revision 1.0:
  22. | original 8088 code from P.S.Housel for double floats
  23.  
  24.     .text
  25.     .even
  26.     .globl    __subsf3, ___subsf3
  27.     .globl    __addsf3, ___addsf3
  28.  
  29. __subsf3:
  30. ___subsf3:
  31.     eorb    #0x80,sp@(8)    | reverse sign of v
  32. __addsf3:
  33. ___addsf3:
  34.     lea    sp@(4),a0    | pointer to u and v parameter
  35.     moveml    d2-d5,sp@-    | save registers
  36.     moveml    a0@,d4/d5    | d4 = v, d5 = u
  37.  
  38.     movel    d5,d0        | d0 = u.exp
  39.     swap    d0
  40.     movel    d5,d2        | d2.h = u.sign
  41.     movew    d0,d2
  42.     lsrw    #7,d0
  43.     andw    #0xff,d0    | kill sign bit (exponent is 8 bits)
  44.  
  45.     movel    d4,d1        | d1 = v.exp
  46.     swap    d1
  47.     eorw    d1,d2        | d2.l = u.sign ^ v.sign
  48.     lsrw    #7,d1
  49.     andw    #0xff,d1    | kill sign bit (exponent is 8 bits)
  50.  
  51.     andl    #0x7fffff,d5    | remove exponent from mantissa
  52.     tstw    d0        | check for zero exponent - no leading "1"
  53.     beq    0f
  54.     orl    #0x800000,d5    | restore implied leading "1"
  55.     bra    1f
  56. 0:    addw    #1,d0        | "normalize" exponent
  57. 1:
  58.     andl    #0x7fffff,d4    | remove exponent from mantissa
  59.     tstw    d1        | check for zero exponent - no leading "1"
  60.     beq    0f
  61.     orl    #0x800000,d4    | restore implied leading "1"
  62.     bra    1f
  63. 0:    addw    #1,d1        | "normalize" exponent
  64. 1:
  65.     clrw    d3        | (put initial zero rounding bits in d3)
  66.     negw    d1        | d1 = u.exp - v.exp
  67.     addw    d0,d1
  68.     beq    5f        | exponents are equal - no shifting neccessary
  69.     bgt    1f        | not equal but no exchange neccessary
  70.     exg    d4,d5        | exchange u and v
  71.     subw    d1,d0        | d0 = u.exp - (u.exp - v.exp) = v.exp
  72.     negw    d1
  73.     tstw    d2        | d2.h = u.sign ^ (u.sign ^ v.sign) = v.sign
  74.     bpl    1f
  75.     bchg    #31,d2
  76. 1:
  77.     cmpw    #24,d1        | is u so much bigger that v is not
  78.     bge    7f        | significant ?
  79.  
  80.     movew    #7-1,d3        | shift u left up to 7 bits to minimize loss
  81. 2:
  82.     addl    d5,d5
  83.     subw    #1,d0        | decrement exponent
  84.     subw    #1,d1        | done shifting altogether ?
  85.     dbeq    d3,2b        | loop if still can shift u.mant more
  86.     clrw    d3
  87.  
  88.     cmpw    #16,d1        | see if fast rotate possible
  89.     blt    4f
  90.     orb    d4,d3        | set rounding bits
  91.     orb    d2,d3
  92.     sne    d2        | "sticky byte"
  93.     movew    d4,d3
  94.     lsrw    #8,d3
  95.     clrw    d4        | rotate by swapping register halfs
  96.     swap    d4
  97.     subw    #16,d1
  98. 0:
  99.     lsrl    #1,d4        | shift v.mant right the rest of the way
  100.     orb    d3,d2        | set "sticky byte" if necessary
  101.     roxrw    #1,d3        | shift into rounding bits
  102. 4:    dbra    d1,0b        | loop
  103.     andb    #1,d2        | see if "sticky bit" should be set
  104.     orb    d2,d3
  105. 5:
  106.     tstw    d2        | are the signs equal ?
  107.     bpl    6f        | yes, no negate necessary
  108.  
  109.     negb    d3        | negate rounding bits and v.mant
  110.     negl    d4
  111. 6:
  112.     addl    d4,d5        | u.mant = u.mant + v.mant
  113.     bcs    7f        | needn not negate
  114.     tstw    d2        | opposite signs ?
  115.     bpl    7f        | do not need to negate result
  116.  
  117.     negb    d3        | negate rounding bits and u.mant
  118.     negl    d5
  119.     notl    d2        | switch sign
  120. 7:
  121.     movel    d5,d4        | move result for normalization
  122.     moveb    d3,d1        | put rounding bits in d1 for norm_sf
  123.     swap    d2        | put sign into d2 (exponent is in d0)
  124.     jmp    norm_sf        | leave registers on stack for norm_sf
  125.  
  126. # else    sfp004
  127.  
  128. | single precision floating point stuff for Atari-gcc using the SFP004
  129. | developed with gas
  130. |
  131. |  single floating point add/subtract routine
  132. |
  133. | M. Ritzert (mjr at dmzrzu71)
  134. |
  135. | 4.10.1990
  136. |
  137. | no NAN checking implemented since the 68881 treats this situation "correct",
  138. | i.e. according to IEEE
  139.  
  140. | addresses of the 68881 data port. This choice is fastest when much data is
  141. | transferred between the two processors.
  142.  
  143. comm =     -6
  144. resp =    -16
  145. zahl =      0
  146.  
  147. | waiting loop ...
  148. |
  149. | wait:
  150. | ww:    cmpiw    #0x8900,a0@(resp)
  151. |     beq    ww
  152. | is coded directly by
  153. |    .long    0x0c688900, 0xfff067f8
  154.  
  155.     .text
  156.     .even
  157.     .globl    __subsf3, ___subsf3
  158.     .globl    __addsf3, ___addsf3
  159.  
  160. __subsf3:
  161. ___subsf3:
  162.     lea    0xfffa50,a0
  163.     movew    #0x4400,a0@(comm)    | load first argument to fp0
  164.     cmpiw    #0x8900,a0@(resp)    | check
  165.     movel    a7@(4),a0@
  166.     movew    #0x4428,a0@(comm)
  167.     .long    0x0c688900, 0xfff067f8
  168.     movel    a7@(8),a0@
  169.     movew    #0x6400,a0@(comm)    | result to d0
  170.     .long    0x0c688900, 0xfff067f8
  171.     movel    a0@,d0
  172.      rts
  173.  
  174. __addsf3:
  175. ___addsf3:
  176.     lea    0xfffa50,a0
  177.     movew    #0x4400,a0@(comm)        | load fp0
  178.     cmpiw    #0x8900,a0@(resp)        | got it?
  179.     movel    a7@(4),a0@            | take a from stack to FPU
  180.     movew    #0x4422,a0@(comm)        | add second arg to fp0
  181.     .long    0x0c688900, 0xfff067f8
  182.     movel    a7@(8),a0@            | move b from stack to FPU
  183.     movew    #0x6400,a0@(comm)        | result to d0
  184.     .long    0x0c688900, 0xfff067f8
  185.     movel    a0@,d0                | download result
  186.      rts
  187.  
  188. # endif    sfp004
  189. #endif    __M68881__
  190.